home *** CD-ROM | disk | FTP | other *** search
/ FishMarket 1.0 / FishMarket v1.0.iso / fishies / 051-075 / disk_069 / make / make.c < prev    next >
C/C++ Source or Header  |  1992-05-06  |  11KB  |  531 lines

  1. /*
  2.  *    Do the actual making for make
  3.  */
  4.  
  5. #include <stdio.h>
  6. #ifdef unix
  7. #include <sys/types.h>
  8. #include <sys/stat.h>
  9. #include <sys/errno.h>
  10. #endif
  11. #ifdef eon
  12. #include <sys/stat.h>
  13. #include <sys/err.h>
  14. #endif
  15. #ifdef os9
  16. #include <time.h>
  17. #include <os9.h>
  18. #include <modes.h>
  19. #include <direct.h>
  20. #include <errno.h>
  21. #endif
  22. #ifdef amiga
  23. #include <ctype.h>
  24. #include <errno.h>
  25. #include <libraries/dosextens.h>
  26. #include <exec/memory.h>
  27. #include <exec/io.h>
  28. #include <exec/ports.h>
  29. #include <functions.h>
  30. #endif
  31. #include "h.h"
  32.  
  33.  
  34.  
  35. /*
  36.  *    Exec a shell that returns exit status correctly (/bin/esh).
  37.  *    The standard EON shell returns the process number of the last
  38.  *    async command, used by the debugger (ugg).
  39.  *    [exec on eon is like a fork+exec on unix]
  40.  */
  41. int
  42. dosh(string, shell)
  43.     char           *string;
  44.     char           *shell;
  45. {
  46.     int             number;
  47.  
  48. #ifdef amiga
  49.     char           *av[3], *s, *p;
  50.     int             i;
  51.  
  52.     p = s = malloc((unsigned) strlen(string) + 1);
  53.     strcpy(p, string);            /* make a copy of the string */
  54.     i = 0;
  55.     av[0] = gettok(&p);            /* get first argument */
  56.     av[1] = p;                /* get rest of command line */
  57.     av[2] = NULL;
  58.     if (fexecv(av[0], av) == -1)
  59.     fatal("couldn't execute command '%s', error return %02x\n",
  60.           av[0], errno);
  61.     number = wait();
  62.     free(s);
  63.     return number;
  64. #endif
  65.  
  66. #ifdef unix
  67.     return system(string);
  68. #endif
  69. #ifdef eon
  70.     return ((number = execl(shell, shell, "-c", string, 0)) == -1) ?
  71.     -1 :            /* couldn't start the shell */
  72.     wait(number);        /* return its exit status */
  73. #endif
  74. #ifdef os9
  75.     int             status, pid;
  76.  
  77.     strcat(string, "\n");
  78.     if ((number = os9fork(shell, strlen(string), string, 0, 0, 0)) == -1)
  79.     return -1;        /* Couldn't start a shell */
  80.     do {
  81.     if ((pid = wait(&status)) == -1)
  82.         return -1;        /* child already died!?!? */
  83.     } while (pid != number);
  84.  
  85.     return status;
  86. #endif
  87. }
  88.  
  89.  
  90. /*
  91.  *    Do commands to make a target
  92.  */
  93. void
  94. docmds1(np, lp)
  95.     struct name    *np;
  96.     struct line    *lp;
  97. {
  98.     bool            ssilent;
  99.     bool            signore;
  100.     int             estat;
  101.     register char  *q;
  102.     register char  *p;
  103.     char           *shell;
  104.     register struct cmd *cp;
  105. #ifdef amiga
  106.     long SetSignal();
  107. #endif
  108.  
  109.  
  110.     if (*(shell = getmacro("SHELL")) == '\0')
  111. #ifdef eon
  112.     shell = ":bin/esh";
  113. #endif
  114. #ifdef unix
  115.     shell = "/bin/sh";
  116. #endif
  117. #ifdef os9
  118.     shell = "shell";
  119. #endif
  120. #ifdef amiga
  121.     shell = NULL;
  122. #endif
  123.  
  124.     for (cp = lp->l_cmd; cp; cp = cp->c_next) {
  125.     strcpy(str1, cp->c_cmd);
  126.     expand(str1);
  127.     q = str1;
  128.     ssilent = silent;
  129.     signore = ignore;
  130.     while ((*q == '@') || (*q == '-')) {
  131.         if (*q == '@')    /* Specific silent  */
  132.         ssilent = TRUE;
  133.         else        /* Specific ignore  */
  134.         signore = TRUE;
  135.         q++;        /* Not part of the command  */
  136.     }
  137.  
  138.     if (!domake)
  139.         ssilent = 0;
  140.  
  141.     if (!ssilent)
  142.         fputs("    ", stdout);
  143.  
  144.     for (p = q; *p; p++) {
  145.         if (*p == '\n' && p[1] != '\0') {
  146.         *p = ' ';
  147.         if (!ssilent)
  148.             fputs("\\\n", stdout);
  149.         } else if (!ssilent)
  150.         putchar(*p);
  151.     }
  152.     if (!ssilent)
  153.         putchar('\n');
  154.  
  155.     if (domake) {        /* Get the shell to execute it  */
  156.         if ((estat = dosh(q, shell)) != 0) {
  157.         if (estat == -1)
  158.             fatal("Couldn't execute %s", shell);
  159.         else {
  160.             printf("%s: Error code %d", myname, estat);
  161.             if (signore)
  162.             fputs(" (Ignored)\n", stdout);
  163.             else {
  164.             putchar('\n');
  165.             if (!(np->n_flag & N_PREC))
  166.                 if (unlink(np->n_name) == 0)
  167.                 printf("%s: '%s' removed.\n", myname, np->n_name);
  168.             exit(estat);
  169.             }
  170.         }
  171.         }
  172. #ifdef amiga
  173.         if ((SetSignal(0L, SIGBREAKF_CTRL_D) & SIGBREAKF_CTRL_D) != 0) {
  174.         fputs("make: abort due to ^D\n", stdout);
  175.         exit(1);
  176.         }
  177. #endif        
  178.     }
  179.     }
  180. }
  181.  
  182.  
  183. docmds(np)
  184.     struct name    *np;
  185. {
  186.     register struct line *lp;
  187.  
  188.  
  189.     for (lp = np->n_line; lp; lp = lp->l_next)
  190.     docmds1(np, lp);
  191. }
  192.  
  193.  
  194. #ifdef os9
  195. /*
  196.  *    Some stuffing around to get the modified time of a file
  197.  *    in an os9 file system
  198.  */
  199. getmdate(fd, tbp)
  200.     struct sgtbuf  *tbp;
  201. {
  202.     struct registers regs;
  203.     static struct fildes fdbuf;
  204.  
  205.  
  206.     regs.rg_a = fd;
  207.     regs.rg_b = SS_FD;
  208.     regs.rg_x = &fdbuf;
  209.     regs.rg_y = sizeof(fdbuf);
  210.  
  211.     if (_os9(I_GETSTT, ®s) == -1) {
  212.     errno = regs.rg_b & 0xff;
  213.     return -1;
  214.     }
  215.     if (tbp) {
  216.     _strass(tbp, fdbuf.fd_date, sizeof(fdbuf.fd_date));
  217.     tbp->t_second = 0;    /* Files are only acurate to mins */
  218.     }
  219.     return 0;
  220. }
  221.  
  222.  
  223. /*
  224.  *    Kludge routine to return an aproximation of how many
  225.  *    seconds since 1980.  Dates will be in order, but will not
  226.  *    be lineer
  227.  */
  228. time_t
  229. cnvtime(tbp)
  230.     struct sgtbuf  *tbp;
  231. {
  232.     long            acc;
  233.  
  234.  
  235.     acc = tbp->t_year - 80;    /* Baseyear is 1980 */
  236.     acc = acc * 12 + tbp->t_month;
  237.     acc = acc * 31 + tbp->t_day;
  238.     acc = acc * 24 + tbp->t_hour;
  239.     acc = acc * 60 + tbp->t_minute;
  240.     acc = acc * 60 + tbp->t_second;
  241.  
  242.     return acc;
  243. }
  244.  
  245.  
  246. /*
  247.  *    Get the current time in the internal format
  248.  */
  249. time(tp)
  250.     time_t         *tp;
  251. {
  252.     struct sgtbuf   tbuf;
  253.  
  254.  
  255.     if (getime(&tbuf) < 0)
  256.     return -1;
  257.  
  258.     if (tp)
  259.     *tp = cnvtime(&tbuf);
  260.  
  261.     return 0;
  262. }
  263. #endif
  264.  
  265.  
  266. /*
  267.  *    Get the modification time of a file.  If the first
  268.  *    doesn't exist, it's modtime is set to 0.
  269.  */
  270. void
  271. modtime(np)
  272.     struct name    *np;
  273. {
  274. #ifdef unix
  275.     struct stat     info;
  276.     int             fd;
  277.  
  278.  
  279.     if (stat(np->n_name, &info) < 0) {
  280.     if (errno != ENOENT)
  281.         fatal("Can't open %s; error %d", np->n_name, errno);
  282.  
  283.     np->n_time = 0L;
  284.     } else
  285.     np->n_time = info.st_mtime;
  286. #endif
  287. #ifdef eon
  288.     struct stat     info;
  289.     int             fd;
  290.  
  291.  
  292.     if ((fd = open(np->n_name, 0)) < 0) {
  293.     if (errno != ER_NOTF)
  294.         fatal("Can't open %s; error %02x", np->n_name, errno);
  295.  
  296.     np->n_time = 0L;
  297.     } else if (getstat(fd, &info) < 0)
  298.     fatal("Can't getstat %s; error %02x", np->n_name, errno);
  299.     else
  300.     np->n_time = info.st_mod;
  301.  
  302.     close(fd);
  303. #endif
  304. #ifdef os9
  305.     struct sgtbuf   info;
  306.     int             fd;
  307.  
  308.  
  309.     if ((fd = open(np->n_name, 0)) < 0) {
  310.     if (errno != E_PNNF)
  311.         fatal("Can't open %s; error %02x", np->n_name, errno);
  312.  
  313.     np->n_time = 0L;
  314.     } else if (getmdate(fd, &info) < 0)
  315.     fatal("Can't getstat %s; error %02x", np->n_name, errno);
  316.     else
  317.     np->n_time = cnvtime(&info);
  318.  
  319.     close(fd);
  320. #endif
  321. #ifdef amiga
  322.     struct FileInfoBlock *fib;
  323.     struct Lock *myLock;
  324.     long ioErr;
  325.  
  326.     fib = (struct FileInfoBlock *) malloc((unsigned) sizeof(struct FileInfoBlock));
  327.     if ((myLock = Lock(np->n_name, ACCESS_READ)) == NULL) {
  328.     if ((ioErr = IoErr()) != ERROR_OBJECT_NOT_FOUND)
  329.         fatal("Can't Lock '%s'; error %3ld", np->n_name, ioErr);
  330.     np->n_time = 0L;
  331.     } else if (!Examine(myLock, fib)) {
  332.     UnLock(myLock);
  333.     fatal("Can't Examine '%s'; error %3ld", np->n_name, IoErr());
  334.     } else {
  335.      np->n_time = fib->fib_Date.ds_Tick/TICKS_PER_SECOND +
  336.          60*fib->fib_Date.ds_Minute + 86400*fib->fib_Date.ds_Days;
  337.         UnLock(myLock);
  338.     }
  339.     free((char *) fib);
  340. #endif
  341.  
  342. }
  343.  
  344.  
  345. /*
  346.  *    Update the mod time of a file to now.
  347.  */
  348. void
  349. touch(np)
  350.     struct name    *np;
  351. {
  352.     char            c;
  353.     int             fd;
  354.  
  355.  
  356.     if (!domake || !silent)
  357.     printf("    touch(%s)\n", np->n_name);
  358.  
  359.     if (domake) {
  360. #ifdef unix
  361.     long            a[2];
  362.  
  363.     a[0] = a[1] = time(0);
  364.     if (utime(np->n_name, &a[0]) < 0)
  365.         printf("%s: '%s' not touched - non-existant\n",
  366.            myname, np->n_name);
  367. #endif
  368. #ifdef eon
  369.     if ((fd = open(np->n_name, 0)) < 0)
  370.         printf("%s: '%s' not touched - non-existant\n",
  371.            myname, np->n_name);
  372.     else {
  373.         uread(fd, &c, 1, 0);
  374.         uwrite(fd, &c, 1);
  375.     }
  376.     close(fd);
  377. #endif
  378. #ifdef os9
  379.     /*
  380.      * Strange that something almost as totally useless as this is easy
  381.      * to do in os9! 
  382.      */
  383.     if ((fd = open(np->n_name, S_IWRITE)) < 0)
  384.         printf("%s: '%s' not touched - non-existant\n",
  385.            myname, np->n_name);
  386.     close(fd);
  387. #endif
  388. #ifdef amiga
  389.     struct MsgPort *task;
  390.     ULONG dateStamp[3];
  391.     struct Lock *lock, *plock;
  392.     UBYTE *pointer;
  393.  
  394.     if(!(pointer= (UBYTE *)AllocMem(64L,MEMF_PUBLIC)))
  395.         fatal("Can't get 64 bytes for pointer");
  396.     if(!(task=(struct MsgPort *)DeviceProc(np->n_name))) {
  397.         printf("%s: can't get MsgPort for '%s'\n", myname, np->n_name);
  398.         FreeMem((void *) pointer, 64L);
  399.         return;
  400.     }
  401.     if(!(lock = Lock(np->n_name,SHARED_LOCK))) {
  402.         printf("%s: '%s' not touched - non-existant\n",
  403.             myname, np->n_name);
  404.         FreeMem((void *) pointer, 64L);
  405.         return;
  406.     }
  407.     plock = ParentDir(lock);
  408.     UnLock(lock);
  409.  
  410.     strcpy((pointer + 1),np->n_name);
  411.     *pointer = strlen(np->n_name);
  412.  
  413.     dos_packet(task, ACTION_SET_DATE, NULL, plock, (ULONG) &pointer[0] >> 2,
  414.         (ULONG) DateStamp(dateStamp), 0L, 0L, 0L);
  415.  
  416.     UnLock(plock);
  417.     FreeMem((void *) pointer, 64L);
  418. #endif
  419.     }
  420. }
  421.  
  422. /*
  423.  * Recursive routine to make a target. 
  424.  */
  425. int
  426. make(np, level)
  427.     struct name    *np;
  428.     int             level;
  429. {
  430.     register struct depend *dp;
  431.     register struct line *lp;
  432.     register struct depend *qdp;
  433.     time_t          dtime = 1, time();
  434.     bool            didsomething = 0;
  435.  
  436.  
  437.     if (np->n_flag & N_DONE)
  438.     return 0;
  439.  
  440.     if (!np->n_time)
  441.     modtime(np);        /* Gets modtime of this file  */
  442.  
  443.     if (rules) {
  444.     for (lp = np->n_line; lp; lp = lp->l_next)
  445.         if (lp->l_cmd)
  446.         break;
  447.     if (!lp)
  448.         dyndep(np);
  449.     }
  450.     if (!(np->n_flag & N_TARG) && np->n_time == 0L)
  451.     fatal("Don't know how to make %s", np->n_name);
  452.  
  453.     for (qdp = (struct depend *) 0, lp = np->n_line; lp; lp = lp->l_next) {
  454.     for (dp = lp->l_dep; dp; dp = dp->d_next) {
  455.         make(dp->d_name, level + 1);
  456.         if (np->n_time < dp->d_name->n_time)
  457.         qdp = newdep(dp->d_name, qdp);
  458.         dtime = max(dtime, dp->d_name->n_time);
  459.     }
  460.     if (!quest && (np->n_flag & N_DOUBLE) && (np->n_time < dtime)) {
  461.         make1(np, lp, qdp);    /* free()'s qdp */
  462.         dtime = 1;
  463.         qdp = (struct depend *) 0;
  464.         didsomething++;
  465.     }
  466.     }
  467.  
  468.     np->n_flag |= N_DONE;
  469.  
  470.     if (quest) {
  471.     long            t;
  472.  
  473.     t = np->n_time;
  474.     time(&np->n_time);
  475.     return t < dtime;
  476.     } else if (np->n_time < dtime && !(np->n_flag & N_DOUBLE)) {
  477.     make1(np, (struct line *) 0, qdp);    /* free()'s qdp */
  478.     time(&np->n_time);
  479.     } else if (level == 0 && !didsomething)
  480.     printf("%s: '%s' is up to date\n", myname, np->n_name);
  481.     return 0;
  482. }
  483.  
  484.  
  485. make1(np, lp, qdp)
  486.     register struct depend *qdp;
  487.     struct line    *lp;
  488.     struct name    *np;
  489. {
  490.     register struct depend *dp;
  491.  
  492.  
  493.     if (dotouch)
  494.     touch(np);
  495.     else {
  496.     strcpy(str1, "");
  497.     for (dp = qdp; dp; dp = qdp) {
  498.         if (strlen(str1))
  499.         strcat(str1, " ");
  500.         strcat(str1, dp->d_name->n_name);
  501.         qdp = dp->d_next;
  502.         free(dp);
  503.     }
  504.     setmacro("?", str1);
  505.     setmacro("@", np->n_name);
  506.     if (lp)            /* lp set if doing a :: rule */
  507.         docmds1(np, lp);
  508.     else
  509.         docmds(np);
  510.     }
  511. }
  512. #ifdef amiga
  513. /*
  514.  * Replace the Aztec-provided time function with one which returns something
  515.  * easy to find and compare, namely the number of seconds since the Amiga's
  516.  * reference date.  This is the same thing returned by modtime() above.
  517.  */
  518. time_t
  519. time(v)
  520.     time_t *v;
  521. {
  522.     long t[3];
  523.  
  524.     DateStamp(t);
  525.     t[0] = t[2]/TICKS_PER_SECOND + 60*t[1] + 86400*t[0];
  526.     if (v)
  527.     *v = t[0];
  528.     return t[0];
  529. }
  530. #endif
  531.